import java.awt.*;

import javax.swing.*;
import java.awt.event.*;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

public class Panel extends JPanel {
	private static final long serialVersionUID = 1L;
	private JTextField txtMinigoogol;
	private JLabel lblLblminigoogol;
	private JButton btnBtnsearch;
	private JTextField txtBrowse;
	private JButton btnBtnbrowse, btnRemoveDocumentIndex, btnBtnupload;
	private JFileChooser chooser;
	private JTextArea txtareasearchresults;
	private JScrollPane jScrollPane;

	static final int x = 100, y = 100;
	static boolean twoDArray[][];

	/* Variables */
	String filename, record, arrOfSearchTerms[];
	BufferedReader bufferedReader;
	HashMap<String, Integer> hashMap;
	ArrayList<String> arrOfRecords, searchResults;
	HashMap<String, ArrayList<String>> hashMapOfRoots;
	ArrayList<String> arrOfRoots, tempArrList = new ArrayList<String>();
	ArrayList<String> arrlistOfSearchTerms = new ArrayList<String>();
	HashSet<String> hashArrOfSearchTerms = new HashSet<String>();

	public Panel() {
		setBackground(Color.CYAN);
		setLayout(null);
		twoDArray = new boolean[x][y];
		/* Initialising the 2d array */
		for (int i = 0; i < x; i++) {
			for (int j = 0; j < y; j++) {
				twoDArray[i][j] = false;
			}
		}
		searchResults = new ArrayList<String>();
		createComponents();
		addListeners();
		addComponents();

	}

	private void createComponents() {
		lblLblminigoogol = new JLabel("Search Engine");
		lblLblminigoogol.setFont(new Font("Dialog", Font.PLAIN, 45));
		lblLblminigoogol.setBounds(43, 24, 357, 55);

		txtMinigoogol = new JTextField();
		txtMinigoogol.setFont(new Font("Dialog", Font.PLAIN, 25));
		txtMinigoogol.setBounds(12, 94, 426, 38);
		txtMinigoogol.setColumns(10);

		btnBtnsearch = new JButton("Search");
		btnBtnsearch.setBounds(450, 105, 84, 25);

		txtBrowse = new JTextField();
		txtBrowse.setText("");
		txtBrowse.setBounds(450, 264, 340, 19);
		txtBrowse.setColumns(10);

		btnBtnbrowse = new JButton("Browse");
		btnBtnbrowse.setBounds(450, 295, 87, 25);

		btnBtnupload = new JButton("Index");
		btnBtnupload.setBounds(574, 295, 84, 25);

		txtareasearchresults = new JTextArea();
		txtareasearchresults.setLineWrap(true);
		txtareasearchresults.setEnabled(false);
		txtareasearchresults.setBackground(Color.BLACK);

		jScrollPane = new JScrollPane(txtareasearchresults);
		jScrollPane.setBounds(12, 144, 426, 206);

		btnRemoveDocumentIndex = new JButton("Remove");
		btnRemoveDocumentIndex.setBounds(695, 295, 95, 25);

	}

	private void addListeners() {

		txtMinigoogol.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				searchTermLogic();
				// buildSuffixTree(txtMinigoogol.getText());
			}
		});

		btnBtnsearch.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				searchTermLogic();
				// buildSuffixTree(txtMinigoogol.getText());
			}
		});

		btnBtnbrowse.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				/* Creating an object of file chooser */
				chooser = new JFileChooser();
				/* To pop up an open file chooser dialog */
				int r = chooser.showOpenDialog(new JFrame());
				/* Getting the filename */
				if (r == JFileChooser.APPROVE_OPTION) {
					/* Getting the filename */
					filename = chooser.getSelectedFile().getAbsolutePath();
					/* Assigning the file name to the text box */
					txtBrowse.setText(filename);
				}
			}
		});

		btnBtnupload.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				/* Checking if already indexed */
				if (Database.retrieveFromDatabase(
						Database.word_links_columns(),
						Database.word_link_table_name,
						Database.word_link_table_name_link + "=\'"
								+ txtBrowse.getText() + "\'") != null) {
					JOptionPane.showMessageDialog(null,
							"Document already indexed");
					return;
				}
				if (txtBrowse.getText().length() != 0) {
					try {
						bufferedReader = new BufferedReader(new FileReader(
								txtBrowse.getText()));

						/* Getting the frequency of words */
						hashMap = Document.getWordfrequency(bufferedReader,
								txtBrowse.getText());
						/* Inserting into the database */
						Document.insert(hashMap, txtBrowse.getText());
						/* Making the text box empty */
						JOptionPane.showMessageDialog(null, "Document Indexed");
						txtBrowse.setText("");
					} catch (Exception ex) {
						JOptionPane.showMessageDialog(null,
								"Not a valid file path");
					}
				} else {
					JOptionPane.showMessageDialog(null, "No File Specified");
				}
			}
		});

		btnRemoveDocumentIndex.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				if (txtBrowse.getText().length() != 0) {
					/* Check if link is present at all or not */
					if (Database.retrieveFromDatabase(
							Database.word_link_table_name_link,
							Database.word_link_table_name,
							Database.word_link_table_name_link + "=\'"
									+ txtBrowse.getText() + "\'") == null) {
						JOptionPane.showMessageDialog(null, "Link not found");
					} else {
						/* Deleting from the database */
						boolean var = Database.deleteFromDatabase(
								Database.word_link_table_name,
								Database.word_link_table_name_link + "=\'"
										+ txtBrowse.getText() + "\'",
								Database.word_link_table_name_link);
						if (var)
							JOptionPane.showMessageDialog(null,
									"links removed from the database");
						else
							JOptionPane.showMessageDialog(null,
									"No link found to be removed");
						txtBrowse.setText("");
					}
				} else {
					JOptionPane.showMessageDialog(null, "No file specified");
				}
			}
		});
	}

	private void searchTermLogic() {
		/* Splitting the search term into words */
		arrOfSearchTerms = Document.tokenizeSearchTerm(txtMinigoogol.getText());
		hashArrOfSearchTerms = new HashSet<String>();
		for (int i = 0; i < arrOfSearchTerms.length; i++) {
			hashArrOfSearchTerms.add(arrOfSearchTerms[i]);
		}
		arrlistOfSearchTerms = new ArrayList<String>(hashArrOfSearchTerms);
		/*
		 * Firstly get the index serial number for the word in the text box
		 */
		for (int i = 0; i < arrlistOfSearchTerms.size(); i++) {
			record = Database.retrieveFromDatabase(
					Database.word_index_table_name_sno,
					Database.word_index_table_name,
					Database.word_index_table_name_word + "=\'"
							+ arrlistOfSearchTerms.get(i).replaceAll("\\W", "") + "\'");
			if (record == null) {
				// JOptionPane.showMessageDialog(null, "Not Indexed "
				// + arrOfSearchTerms.length);
				txtareasearchresults.setText("No Results");
			} else {
				/* To get all the links that record is pointing to */
				arrOfRecords = Database.retrieveAllFromDatabase(
						Database.word_link_table_name_link,
						Database.word_link_table_name,
						Database.word_link_table_name_sno + "=\'" + record
								+ "\'");
				if (arrOfRecords == null) {
					// JOptionPane.showMessageDialog(null,
					// "No link found for the word");
					txtareasearchresults.setText("No Results");
				} else {
					// JOptionPane.showMessageDialog(null,
					// "Record present");
					/*
					 * This function will check the index and create a 2-d array
					 * so that we know in which all pages the word is present
					 */
					Document.booleanRetrievalSystem(
							arrlistOfSearchTerms.get(i).replaceAll("\\W", ""),
							arrOfRecords, twoDArray);
				}
			}
		}
		/*
		 * Function to create the print the 2d boolean array
		 */
		/* Document.displayBooleanArray(twoDArray); */
		/**************************************************/
		/*
		 * Function to scan the boolean 2 d array and give the search results
		 */
		// searchResults = Document.getResults(twoDArray);
		/* This function will define the order of links */
		searchResults = Document.getAllSearchResults(twoDArray);
		/**************************************************/
		if (searchResults.size() != 0) {
			/*********************************************************/
			/* Function to show the search results in the text area */
			txtareasearchresults.setText(PrintClass.printSearchResults(
					searchResults, arrlistOfSearchTerms));
			/*********************************************************/
			// JOptionPane.showMessageDialog(null, searchResults);
		} else {
			// JOptionPane.showMessageDialog(null, "No results");
			txtareasearchresults.setText("No results");
		}
		/* Initialising the 2d array */
		for (int i = 0; i < x; i++) {
			for (int j = 0; j < y; j++) {
				twoDArray[i][j] = false;
			}
		}
		/* Initializig th objects once again */
		Document.rowCounter = 0;
		Document.columnCounter = 0;
		Document.rowHashMap = new HashMap<String, Integer>();
		Document.columnHashMap = new HashMap<String, Integer>();
		Document.countOfNoOfTrues = new HashMap<Integer, Integer>();
		/* Putting the cursor right at the beginning */
	}

	@SuppressWarnings("unused")
	private void buildSuffixTree(String searchTerm) {
		/* Suffix tree because we are giving suggestions for the suffixes */
		/* Firstly we need to clean up the text */
		/* .replaceAll("\\W", "") */
		String term = "", substring = "";
		boolean notInside = true;
		String[] arrayOfSearchTerms = Document.tokenizeSearchTerm(searchTerm);
		for (int i = 0; i < arrayOfSearchTerms.length; i++) {
			term = term + arrayOfSearchTerms[i].replaceAll("\\W", "") + " ";
		}
		term = term.trim();
		/* Creating an array list of roots */
		hashMapOfRoots = new HashMap<String, ArrayList<String>>();
		arrOfRoots = new ArrayList<String>();

		/* Loop in the search term to build the suffix tree */
		for (int i = term.length() - 1; i >= 0; i--) {
			substring = term.substring(i);
			notInside = true;
			/*
			 * If the character is present then don't add else ad so for cas it
			 * will check ca, cag etc
			 */
			/*
			 * reverse because we need to go into the branch that has the best
			 * match and that can come only when we start from the end
			 */
			boolean loopBreak = false;
			for (int j = substring.length(); j > 0; j--) {
				for (String str : arrOfRoots) {
					if (str.contains(substring.substring(0, j))) {
						notInside = false;
						traverseTree(substring.substring(j), str,
								hashMapOfRoots, j, arrOfRoots);
						loopBreak = true;
						break;
					}
				}
				if (loopBreak) {
					loopBreak = false;
					break;
				}
			}

			/* If it did not go inside it should go inside here */
			if (notInside) {
				/* Every string should have an array of strings i.e a graph */
				hashMapOfRoots.put(substring, new ArrayList<String>());
				arrOfRoots.add(substring);
			}
		}
	}

	/* To get the particular */
	private void traverseTree(String substr, String rootStr,
			HashMap<String, ArrayList<String>> hashMapOfRoots,
			int breakingIndex, ArrayList<String> arrOfRoots) {

		if (hashMapOfRoots.get(rootStr).contains(substr)) {
			traverseTree(substr.substring(1), substr, hashMapOfRoots,
					breakingIndex, arrOfRoots);
		} else {
			if (rootStr.length() != breakingIndex) {
				/* Get the araylist it was pointing to */
				tempArrList = hashMapOfRoots.get(rootStr);
				/* Adding the new node */
				tempArrList.add(substr);
				/* Adding the string at which it broke */
				tempArrList.add(rootStr.substring(breakingIndex));
				/* Now we remove that particular entry */
				hashMapOfRoots.remove(rootStr);
				arrOfRoots.remove(rootStr);
				hashMapOfRoots.put(rootStr.substring(0, breakingIndex),
						tempArrList);
				arrOfRoots.add(rootStr.substring(0, breakingIndex));
			} else {
				hashMapOfRoots.get(rootStr).add(substr);
			}
			return;
		}
	}

	@SuppressWarnings("unused")
	private String getSuggestion(ArrayList<String> arrOfRoots,
			HashMap<String, ArrayList<String>> hashMapOfRoots, String searchTerm) {
		/* Now we cleaned the text */
		// searchTerm=Document.reformedSearchTerm(searchTerm);
		String matchedString = "";
		/* First we need to search n the roots list O(n) */
		for (String str : arrOfRoots) {
			if (str.equals(searchTerm)) {
				matchedString = str;
				return traverseSuffixTree(hashMapOfRoots, matchedString, 0);
			}
		}
		return "";
	}

	String term = "";

	private String traverseSuffixTree(
			HashMap<String, ArrayList<String>> hashMapOfRoots,
			String matchedString, int index) {

		if (hashMapOfRoots.get(matchedString).get(index) != null) {
			if (hashMapOfRoots.get(matchedString).size() > index) {
				traverseSuffixTree(hashMapOfRoots,
						hashMapOfRoots.get(matchedString).get(0), 0);
				return term;
			} else {
				/* Now we got the first string the arraylist */
				term = term + hashMapOfRoots.get(matchedString).get(index);
				/* No we give the same string and go to its root */
				traverseSuffixTree(hashMapOfRoots,
						hashMapOfRoots.get(matchedString).get(index), index);
				return term;
			}
		} else {
			/* If the first condition fails then we need to go ahead */
			term = term + " ";
			traverseSuffixTree(hashMapOfRoots, hashMapOfRoots
					.get(matchedString).get(index), index++);
			return term;
		}
	}

	private void addComponents() {
		add(lblLblminigoogol);
		add(txtMinigoogol);
		add(btnBtnsearch);
		add(txtBrowse);
		add(btnBtnbrowse);
		add(btnBtnupload);
		add(jScrollPane);
		add(btnRemoveDocumentIndex);
	}
}
